//
//  WJPDFDrawLine.swift
//  PDFSign
//
//  Created by 李永彬 on 2025/9/23.
//

import UIKit

class WJPDFDrawLine {
    private(set) var points: [CGPoint]
    let color: UIColor
    let width: CGFloat
    private(set) var erasedPoints: Set<Int> = []
    
    // 单个点也是有效的
    private let minPoints = 1
    
    // 优化的控制点计算
    private(set) var controlPoints: [(in: CGPoint, out: CGPoint)] = []
    
    init(startPoint: CGPoint, color: UIColor, width: CGFloat) {
        self.points = [startPoint]
        self.color = color
        self.width = width
    }
    
    // 优化点的添加逻辑，控制采样频率
    func addPoint(_ point: CGPoint) {
        guard let lastPoint = points.last else {
            points.append(point)
            return
        }
        
        // 计算与最后一个点的距离
        let distance = hypot(point.x - lastPoint.x, point.y - lastPoint.y)
        
        // 根据距离动态调整采样率，快速移动时保留更多点
        let minDistance: CGFloat = distance > 10 ? 2 : 1.5
        
        if distance > minDistance {
            points.append(point)
            calculateControlPoints()
        }
    }
    
    func erasePoint(at index: Int) {
        guard index >= 0, index < points.count else { return }
        erasedPoints.insert(index)
    }
    
    var isValid: Bool {
        return visiblePoints.count >= minPoints
    }
    
    var visiblePoints: [CGPoint] {
        return points.enumerated()
            .filter { !erasedPoints.contains($0.offset) }
            .map { $0.element }
    }
    
    func getVisibleSegments() -> [[CGPoint]] {
        var segments: [[CGPoint]] = []
        var currentSegment: [CGPoint] = []
        
        for (index, point) in points.enumerated() {
            if erasedPoints.contains(index) {
                if currentSegment.count >= minPoints {
                    segments.append(currentSegment)
                }
                currentSegment.removeAll()
            } else {
                currentSegment.append(point)
            }
        }
        
        if currentSegment.count >= minPoints {
            segments.append(currentSegment)
        }
        
        return segments
    }
    
    // 改进的控制点计算，使用三次贝塞尔曲线的进出控制点
    private func calculateControlPoints() {
        controlPoints.removeAll()
        guard points.count >= 2 else { return } // 至少需要2个点才能计算控制点
        
        for i in 0..<points.count {
            // 第一个点只计算出控制点
            if i == 0 {
                let p0 = points[i]
                let p1 = points[i+1]
                let outControl = CGPoint(
                    x: p0.x + (p1.x - p0.x) / 3,
                    y: p0.y + (p1.y - p0.y) / 3
                )
                controlPoints.append((in: .zero, out: outControl))
            }
            // 最后一个点只计算入控制点
            else if i == points.count - 1 {
                let pPrev = points[i-1]
                let pCurrent = points[i]
                let inControl = CGPoint(
                    x: pCurrent.x - (pCurrent.x - pPrev.x) / 3,
                    y: pCurrent.y - (pCurrent.y - pPrev.y) / 3
                )
                controlPoints.append((in: inControl, out: .zero))
            }
            // 中间点计算入控制点和出控制点
            else {
                let pPrev = points[i-1]
                let pCurrent = points[i]
                let pNext = points[i+1]
                
                // 计算入控制点（基于前一个点和当前点）
                let inControl = CGPoint(
                    x: pCurrent.x - (pNext.x - pPrev.x) / 6,
                    y: pCurrent.y - (pNext.y - pPrev.y) / 6
                )
                
                // 计算出控制点（基于当前点和下一个点）
                let outControl = CGPoint(
                    x: pCurrent.x + (pNext.x - pPrev.x) / 6,
                    y: pCurrent.y + (pNext.y - pPrev.y) / 6
                )
                
                controlPoints.append((in: inControl, out: outControl))
            }
        }
    }
}
